package main

import (
	"encoding/json"
	"fmt"
	"gitee.com/xjietop/xjutils"
	"log"
	"reflect"
	"strconv"
	"time"
)

type PactProductListDto struct {
	/**
	 * 合同主键标识
	 */
	PactSid int64 `form:"pactSid"`
	/**
	 * 合同编号
	 */
	PactCode string `form:"pactCode"`
	/**
	 * 添加品种列表
	 */
	ProductList []PactProduct `form:"productList"`
	/**
	 * 添加品种 结算类型
	 */
	PactProductAccountList []PactProductAccount `form:"pactProductAccountList"`
	/**
	 * 品种保证金信息列表
	 */
	BailList []PactBail `form:"bailList"`
	/**
	 * 多品授信金额信息表列表
	 */
	ProductCreditList []PactProductCredit `form:"productCreditList"`
	/**
	 * 1:提交
	 */
	DataStatus int `form:"dataStatus"`
}
type PactProduct struct {
	CreateUser      string    `gorm:"column:create_user;type:varchar(32)"`             // 创建人
	CreatedAt       time.Time `gorm:"column:create_time;type:datetime"`                // 创建时间
	UpdateUser      string    `gorm:"column:update_user;type:varchar(32)"`             // 更新人
	UpdatedAt       time.Time `gorm:"column:update_time;type:datetime"`                // 更新时间
	CreateUserSid   int64     `gorm:"column:create_user_sid;type:bigint(20)"`          // 创建人标识
	UpdateUserSid   int64     `gorm:"column:update_user_sid;type:bigint(20)"`          // 修改人标识
	Sid             int64     `gorm:"primary_key;column:sid;type:bigint(20);not null"` // sid
	PactSid         int64     `gorm:"column:pact_sid;type:bigint(20)"`                 // 合同主键标识
	PactCode        string    `gorm:"column:pact_code;type:varchar(32)"`               // 合同编号
	ProductSid      int64     `gorm:"column:product_sid;type:bigint(20)"`              //品种编码Sid
	ProductCode     string    `gorm:"column:product_code;type:varchar(32)"`            // 品种编码
	ProductName     string    `gorm:"column:product_name;type:varchar(128)"`           // 品种名称
	Spec            string    `gorm:"column:spec;type:varchar(32)"`                    // 规格
	SaleDeptSid     int64     `gorm:"column:sale_dept_sid;type:bigint(20)"`            // 销售部门标识
	SalseDeptName   string    `gorm:"column:salse_dept_name;type:varchar(32)"`         // 销售部门名称
	BrandSid        int64     `gorm:"column:brand_sid;type:bigint(20)"`                // 商标标识
	ProductType     int8      `gorm:"column:product_type;type:tinyint(4)"`             // 商品类型
	PurchasePrice   float64   `gorm:"column:purchase_price;type:decimal(32,8)"`        // 采购价
	BoxTexture      string    `gorm:"column:box_texture;type:varchar(32)"`             // 盒子材质
	BoxSize         string    `gorm:"column:box_size;type:varchar(32)"`                // 小盒内径尺寸
	PackingSize     string    `gorm:"column:packing_size;type:varchar(32)"`            // 装箱内径尺寸
	PackingWay      string    `gorm:"column:packing_way;type:varchar(32)"`             // 装箱方法
	BatchQuantity   string    `gorm:"column:batch_quantity;type:varchar(32)"`          // 批次量
	ProductionCycle string    `gorm:"column:production_cycle;type:varchar(32)"`        // 生产周期
	QualityStandard string    `gorm:"column:quality_standard;type:varchar(1024)"`      // 质量标准
	Remark          string    `gorm:"column:remark;type:varchar(128)"`                 // 备注
	TaskType        string    `gorm:"column:task_type;type:varchar(50)"`               // 任务类型
	BailType        string    `gorm:"column:bail_type;type:varchar(50)"`               // 保证金类型
	CreditType      string    `gorm:"column:credit_type;type:varchar(50)"`             // 授信金额类型
}
type PactBail struct {
	CreateUser    string    `gorm:"column:create_user;type:varchar(32)"`             // 创建人
	CreatedAt     time.Time `gorm:"column:create_time;type:datetime"`                // 创建时间
	UpdateUser    string    `gorm:"column:update_user;type:varchar(32)"`             // 更新人
	UpdatedAt     time.Time `gorm:"column:update_time;type:datetime"`                // 更新时间
	CreateUserSid int64     `gorm:"column:create_user_sid;type:bigint(20)"`          // 创建人标识
	UpdateUserSid int64     `gorm:"column:update_user_sid;type:bigint(20)"`          // 修改人标识
	Sid           int64     `gorm:"primary_key;column:sid;type:bigint(20);not null"` // sid
	PactCode      string    `gorm:"column:pact_code;type:varchar(32)"`               // 合同编号
	PactSid       int64     `gorm:"column:pact_sid;type:bigint(20)"`                 // 合同主键
	ProductCode   string    `gorm:"column:product_code;type:varchar(32)"`            // 品种编号
	ProductSid    int64     `gorm:"column:product_sid;type:bigint(20)"`              // 品种主键
	ProductName   string    `gorm:"column:product_name;type:varchar(32)"`            // 品种名称
	BailType      int8      `gorm:"column:bail_type;type:tinyint(4)"`                // 保证金类型
	BailMoney     float64   `gorm:"column:bail_money;type:decimal(32,8)"`            // 保证金额
	BackTime      *time.Time `gorm:"column:back_time;type:datetime"`                  // 返还时间
}
type PactProductAccount struct {
	CreateUser          string    `gorm:"column:create_user;type:varchar(32)"`             // 创建人
	CreatedAt           time.Time `gorm:"column:create_time;type:datetime"`                // 创建时间
	UpdateUser          string    `gorm:"column:update_user;type:varchar(32)"`             // 更新人
	UpdatedAt           time.Time `gorm:"column:update_time;type:datetime"`                // 更新时间
	CreateUserSid       int64     `gorm:"column:create_user_sid;type:bigint(20)"`          // 创建人标识
	UpdateUserSid       int64     `gorm:"column:update_user_sid;type:bigint(20)"`          // 修改人标识
	Sid                 int64     `gorm:"primary_key;column:sid;type:bigint(20);not null"` // sid
	PactCode            string    `gorm:"column:pact_code;type:varchar(32)"`               // 合同编号
	PactSid             int64     `gorm:"column:pact_sid;type:bigint(20)"`                 // 合同主键
	ProductCode         string    `gorm:"column:product_code;type:varchar(32)"`            // 品种编号
	ProductSid          int64     `gorm:"column:product_sid;type:bigint(20)"`              // 品种主键
	ProductName         string    `gorm:"column:product_name;type:varchar(32)"`            // 品种名称
	Prepayment          float64   `gorm:"column:prepayment;type:decimal(32,8)"`            // 采购预付
	PaymentGoods        float64   `gorm:"column:payment_goods;type:decimal(32,8)"`         // 提货付款
	Retainage           float64   `gorm:"column:retainage;type:decimal(32,8)"`             // 尾款
	RetainageDate       string    `gorm:"column:retainage_date;type:varchar(10)"`          // 尾款账期
	Days                int8      `gorm:"column:days;type:tinyint(4)"`                     // 工作日0是1否
	BatchNum            int       `gorm:"column:batch_num;type:int(11)"`                   // 压批数量
	AppointBatchNum     int       `gorm:"column:appoint_batch_num;type:int(11)"`           // 指定批次数量
	AccountType         int       `gorm:"column:account_type;type:int(11)"`                // 结算类型
	AccountRate         float64   `gorm:"column:account_rate;type:decimal(32,8)"`          // 结算承兑比率
	AccountCheckingDate string    `gorm:"column:account_checking_date;type:varchar(10)"`   // 结算对帐日
	AccountDate         string    `gorm:"column:account_date;type:varchar(32)"`            // 结账日
}
type PactProductCredit struct {
	CreateUser    string    `gorm:"column:create_user;type:varchar(32)"`             // 创建人
	CreatedAt     time.Time `gorm:"column:create_time;type:datetime"`                // 创建时间
	UpdateUser    string    `gorm:"column:update_user;type:varchar(32)"`             // 更新人
	UpdatedAt     time.Time `gorm:"column:update_time;type:datetime"`                // 更新时间
	CreateUserSid int64     `gorm:"column:create_user_sid;type:bigint(20)"`          // 创建人标识
	UpdateUserSid int64     `gorm:"column:update_user_sid;type:bigint(20)"`          // 修改人标识
	Sid           int64     `gorm:"primary_key;column:sid;type:bigint(20);not null"` // sid
	PactCode      string    `gorm:"column:pact_code;type:varchar(32)"`               // 合同编号
	PactSid       int64     `gorm:"column:pact_sid;type:bigint(20)"`                 // 合同主键
	ProductCode   string    `gorm:"column:product_code;type:varchar(32)"`            // 品种编号
	ProductSid    int64     `gorm:"column:product_sid;type:bigint(20)"`              // 品种主键
	ProductName   string    `gorm:"column:product_name;type:varchar(32)"`            // 品种名称
	CreditMoney   float64   `gorm:"column:credit_money;type:decimal(32,8)"`          // 授信金额
	CreditDate    string    `gorm:"column:credit_date;type:varchar(50)"`             // 授信结账日
	CreditType    int8      `gorm:"column:credit_type;type:tinyint(4)"`              // 授信类型
}

func main() {
	str := `{"pactSid":7,"pactCode":"mng210111","productList":[{"productCode":"SPH100010364","productName":"阿胶补血口服液（善举）","productSid":14528,"spec":"20毫升/支×12支/盒","containedQuantity":"","weightUnitSid":"","producingArea":"郑州瑞星药业有限公司","brandSid":2,"brandName":"初心","saleDeptSid":1,"salseDeptName":"乐赛仙","productType":1,"purchasePrice":"12","boxTexture":"","batchQuantity":"","boxSize":"","packingSize":"","packingWay":"","productionCycle":"","qualityStandard":"","remark":"","accountType":"","accountTypeName":"实销月结","taskType":"","bailType":1,"bailTypeName":"单品保证金","creditType":"","creditTypeName":"","pactSid":7,"pactCode":"mng210111","supplierSid":1310,"pactSupplierSid":8,"supplierCode":"GYS00000030"}],"pactProductAccountList":[{"accountType":5269,"accountRate":5,"accountCheckingDate":2,"accountDate":5,"batchNum":"","appointBatchNum":"","prepayment":"","paymentGoods":"","retainage":"","retainageDate":"","days":"","pactSid":7,"pactCode":"mng210111","productCode":"SPH100010364","productName":"阿胶补血口服液（善举）","productSid":14528,"accountWay":1}],"productCreditList":[{"creditType":"","creditMoney":"","creditDate":"","productCode":"SPH100010364","productSid":14528,"productName":"阿胶补血口服液（善举）","pactSid":7,"pactCode":"mng210111"}],"bailList":[{"bailType":1,"bailMoney":"1200","backTime":"2021-01-31 00:00:00","productCode":"SPH100010364","productSid":14528,"productName":"阿胶补血口服液（善举）","pactSid":7,"pactCode":"mng210111"}],"dataStatus":0}`
	var params map[string]interface{}
	json.Unmarshal([]byte(str), &params)
	var pactProductListDto PactProductListDto
	MapToEntityWithOutTypeDeep(params, &pactProductListDto)
	fmt.Printf("%v \n", pactProductListDto)
}

//Map转实体类(包含子struct)
func MapToEntityWithOutTypeDeep(src map[string]interface{}, dst interface{}) interface{} {
	dval := reflect.ValueOf(dst).Elem()
	for k, v := range src {
		key := xjutils.Capitalize(k)
		//println(key)
		dvalue := dval.FieldByName(key)
		if !dvalue.IsValid() {
			log.Printf("%s is not found. \n", key)
			continue
		}
		valueStr := ""
		srcType := ""
		switch v.(type) {
		case string:
			srcType = "string"
			valueStr = v.(string)
		case int64:
			srcType = "int64"
			valueStr = strconv.FormatInt(v.(int64), 10)
		case float64:
			srcType = "float64"
			valueStr = strconv.FormatFloat(v.(float64), 'f', -1, 64)
		case []interface{}:
			srcType = "[]interface{}"
			if dvalue.Type().Kind() == reflect.Slice {
				SliceReflect := reflect.MakeSlice(dvalue.Type(), 0, 0)
				for _, item := range v.([]interface{}) {
					typ := dvalue.Type().Elem()
					ditem := reflect.New(typ)
					dst := MapToEntityWithOutTypeDeep(item.(map[string]interface{}), ditem.Interface())
					SliceReflect = reflect.Append(SliceReflect, reflect.ValueOf(dst).Elem())
				}
				dvalue.Set(SliceReflect)
				continue
			}
		default:
			srcType = "other"
			log.Printf("not do,field is %s,src type is %s.\n", key, srcType)
		}
		tgtType := dvalue.Type().Name()
		ptr := false
		if dvalue.Type().Kind().String() == "ptr" {
			elem := dvalue.Type().Elem()
			tgtType = elem.Name()
			ptr = true
		}
		if srcType == tgtType {
			//fmt.Printf("same,field is %s,src type is %s,tgt type is %s.\n",key,srcType,tgtType)
			vv := reflect.ValueOf(v)
			dvalue.Set(vv)
		} else {
			//fmt.Printf("diff,field is %s,src type is %s,tgt type is %s.\n",key,srcType,tgtType)
			switch tgtType {
			case "string":
				vv := reflect.ValueOf(valueStr)
				dvalue.Set(vv)
			case "int":
				v, _ := strconv.Atoi(valueStr)
				vv := reflect.ValueOf(v)
				dvalue.Set(vv)
			case "int8":
				v, _ := strconv.Atoi(valueStr)
				v2 := int8(v)
				vv := reflect.ValueOf(v2)
				dvalue.Set(vv)
			case "int64":
				v, _ := strconv.ParseInt(valueStr, 10, 64)
				vv := reflect.ValueOf(v)
				dvalue.Set(vv)
			case "float64":
				v, _ := strconv.ParseFloat(valueStr, 10)
				vv := reflect.ValueOf(v)
				dvalue.Set(vv)
			case "Time":
				if len(valueStr) == 10 {
					v, _ := time.ParseInLocation("2006-01-02", valueStr, time.Local)
					if ptr {
						vv := reflect.ValueOf(&v)
						dvalue.Set(vv)
					}else{
						vv := reflect.ValueOf(v)
						dvalue.Set(vv)
					}
				} else if len(valueStr) == 19 {
					v, _ := time.ParseInLocation("2006-01-02 15:04:05", valueStr, time.Local)
					if ptr {
						vv := reflect.ValueOf(&v)
						dvalue.Set(vv)
					}else{
						vv := reflect.ValueOf(v)
						dvalue.Set(vv)
					}
				} else {
					//v, _ := time.ParseInLocation("2006-01-02", "0000-01-01", time.Local)
					//vv := reflect.ValueOf(v)
					//dvalue.Set(vv)
				}
			default:
				log.Printf("error:field is %s,src type is %s,tgt type is %s, kind is %s.\n", key, srcType, tgtType, dvalue.Type().Kind().String())
			}
		}
	}
	return dst
}
